using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Html;
using System.Runtime.CompilerServices;
using Minions.Classes;
using Nsb.Classes;
using ThemeChain;
using jQueryApi;

namespace MinionsEdit.Classes
{
    [IgnoreNamespace]
    public static class MiMask
    {
        private static jQueryObject _mask1;
        private static jQueryObject _mask2;
        private static jQueryObject _sizer;
        private static Pos _pos;
        private static double _wd;
        private static double _ht;
        private static bool _once;

        private static readonly Dictionary Css = new Dictionary(
            "position", "absolute",
            "border", "2px dotted #f444f4",
            "color", "transparent",
            "background-color", "transparent",
            "margin", 0,
            "padding", 0
            )
            ;

        private static readonly Dictionary Sizercss = new Dictionary(
            "position", "absolute",
            "width", 10,
            "height", 10,
            "color", "transparent",
            "margin", 0,
            "padding", 0,
            "text-align", "center",
            "z-index", 1
            )
            ;

        static MiMask()
        {
            CreateMask();
        }

        private static void CreateMask()
        {
            _once = false;
            jQuery.Select(".MinionSizer").Remove();
            jQuery.Select(".MinionMask").Remove();

            _mask1 = jQuery.FromHtml("<div class='MinionMask'/>")
                .CSS(Css)
                ;
            _mask2 = jQuery.FromHtml("<div class='MinionMask'/>")
                .CSS(Css)
                .CSS(new Dictionary("border-color", "#f4f444", "border-style", "solid"))
                ;
            _sizer = jQuery.FromHtml("<div class='MinionSizer'/>")
                .CSS(Sizercss)
                .AppendTo(_mask1)
                ;
        }

        private static void GetMetrics(jQueryObject el)
        {
            int offsetTop = Number.ParseInt(el.GetCSS("border-top-width")) /*+ Number.ParseInt(el.GetCSS("padding-top"))*/+ 3;
            int offsetLeft = Number.ParseInt(el.GetCSS("border-left-width")) /*+ Number.ParseInt(el.GetCSS("padding-left"))*/+ 3;
            _pos = new Pos();
            _wd = el.GetOuterWidth();
            _ht = el.GetOuterHeight();
            _pos.Top -= offsetTop;
            _pos.Left -= offsetLeft;
        }

        private static void ReMask(Minion mm)
        {
            if (mm != null)
            {
                if (!_once)
                {
                    // To pick up fixed Uri.Img path
                    _sizer
                        .Append(jQuery.FromHtml("<img src='" + Uri.Img("Common/dragger.png") + "' style='position:absolute;top:0;left:0;width:100%;height:100%'/>"))
                        .MouseDown(SizerEv)
                        ;
                    _once = true;
                }
                GetMetrics(mm.Element);
                //int dd = -2 - (_ht - _innerHt);
                Dictionary<string, string> bdrrad = new Dictionary("border-radius", mm.Element.GetCSS("border-top-left-radius"));
                _mask1
                    .PrependTo(mm.Element)
                    .CSS(new Dictionary("top", _pos.Top, "left", _pos.Left, "width", _wd, "height", _ht))
                    .Plugin<Jewl>().CopyRadius(bdrrad, 2, "px")
                    .Show()
                    ;
                _mask2
                    .PrependTo(mm.Element)
                    .CSS(new Dictionary("top", _pos.Top, "left", _pos.Left, "width", _wd, "height", _ht))
                    .Plugin<Jewl>().CopyRadius(bdrrad, 2, "px")
                    .Show()
                    ;
                _sizer
                    .CSS(new Dictionary("top", _ht - 6, "left", _wd - 6))
                    ;
                if (!_mask1.Is(":visible"))
                {
                    // TODO: Something causes .Show() to stop working in chrome. This kludges around it.
                    Inform.Error("ReMask not visible id={0}", mm.Data.id);
                    CreateMask();
                    ReMask(mm);
                }
            }
        }

        private static void SizerEv(jQueryEvent e)
        {
            if (MinionEdit.ActiveFocus != null)
            {
                new Evo().Evoke(MinionEdit.ActiveFocus.Resize).Ev(e).Fire();
            }
        }

        public static void MaskOn(MinionEdit mm)
        {
            if (MinionEdit.MaskSleeping)
                return;
            if (mm != null)
            {
                //Inform.Debug("MaskOn1 id={0}", mm.Data.id);
                if (_mask1.Parent()[0] != mm.Element[0])
                {
                    ReMask(mm);
                }
                else
                {
                    _mask1.Show();
                    _mask2.Show();
                    if (!_mask1.Is(":visible"))
                    {
                        // TODO: Something causes .Show() to stop working in chrome. This kludges around it.
                        Inform.Error("MaskOn not visible id={0}", mm.Data.id);
                        CreateMask();
                        ReMask(mm);
                    }
                }
            }
            else
                Inform.Debug("MaskOn2");
        }

        public static void MaskOff()
        {
            //Inform.Debug("MaskOff id={0}", mm.Data.id);
            _mask1.AppendTo(Document.Body).Hide();
            _mask2.AppendTo(Document.Body).Hide();
            MinionEdit.MaskSleeping = false;
        }

        public static void MaskSleep()
        {
            MaskOff();
            MinionEdit.MaskSleeping = true;
        }

        public static void MaskWake(MinionEdit mm)
        {
            Debug.Assert(mm != null, "Requires MinionEdit arg");
            MinionEdit.MaskSleeping = false;
            MaskOn(mm);
            ReMask(mm);
        }

        public static void MaskRubberband(MinionEdit mm)
        {
            Debug.Assert(mm != null, "Requires MinionEdit arg");
            ReMask(mm);
        }

        public static void DropMaskOn(MinionEdit mm, jQueryUiObject ui)
        {
            Debug.Assert(mm != null, "Requires MinionEdit arg");
            // ReSharper disable PossibleNullReferenceException
            Inform.Log("DropOver id={0}:{1}", mm.Element[0].TagName, mm.Id);
            // ReSharper restore PossibleNullReferenceException
            jQuery.FromHtml("<div class='DropMask'/>")
                .Html(ThemeBase.Hearts)
                .CSS(new Dictionary(
                         "position", "absolute",
                         "top", 0, "left", 0,
                         "color", "red"
                         ))
                .AppendTo(mm.Element)
                ;
            mm.AddClass("DropOver");
        }

        public static void DropMaskOff(MinionEdit mm, jQueryUiObject ui)
        {
            Debug.Assert(mm != null && ui != null, "Requires MinionEdit and ui arg");
            // ReSharper disable PossibleNullReferenceException
            Inform.Log("DropOut id={0}:{1}", mm.Element[0].TagName, mm.Id);
            // ReSharper restore PossibleNullReferenceException
            jQuery.Select(".DropMask").Remove();
            jQuery.Select(".DropOver").RemoveClass("DropOver");
        }
    }
}